from __future__ import annotations

import os
import re
import sys
from typing import Iterable, List, Set, Optional
from datetime import datetime, timezone


_COLOR_MODE = "auto"  # auto|always|never


def set_color_mode(mode: str) -> None:
    global _COLOR_MODE
    if mode in ("auto", "always", "never"):
        _COLOR_MODE = mode


def _should_color() -> bool:
    if _COLOR_MODE == "always":
        return True
    if _COLOR_MODE == "never":
        return False
    # auto: color only if stdout is a TTY and AW_COLOR env says yes
    env = os.getenv("AW_COLOR", "").lower()
    if env in ("1", "true", "yes", "always"):
        return True
    try:
        return sys.stdout.isatty()
    except Exception:
        return False


def color(text: str, fg: str = "") -> str:
    if not _should_color():
        return text
    codes = {
        "red": "31", "green": "32", "yellow": "33", "blue": "34",
        "magenta": "35", "cyan": "36", "bold": "1",
    }
    if fg not in codes:
        return text
    return f"\x1b[{codes[fg]}m{text}\x1b[0m"


MENTION_RE = re.compile(r"@([A-Za-z0-9_-]+)")


def extract_mentions(text: str, known_ids: Iterable[str]) -> List[str]:
    ids: Set[str] = set(known_ids)
    found = set(m.group(1) for m in MENTION_RE.finditer(text or ""))
    return sorted(list(found.intersection(ids)))


def parse_iso(s: Optional[str]) -> Optional[datetime]:
    """Parse an ISO-like timestamp or date (YYYY-MM-DD). Returns aware UTC dt.

    Accepts strings with trailing 'Z' or with timezone offset. Date-only values
    are interpreted at 00:00:00Z of that day.
    """
    if not s:
        return None
    s = s.strip()
    try:
        if len(s) == 10 and s[4] == '-' and s[7] == '-':
            # date only
            dt = datetime.fromisoformat(s + 'T00:00:00+00:00')
            return dt
        if s.endswith('Z'):
            s = s[:-1] + '+00:00'
        dt = datetime.fromisoformat(s)
        # Ensure timezone-aware
        if dt.tzinfo is None:
            dt = dt.replace(tzinfo=timezone.utc)
        return dt
    except Exception:
        return None
